hdu-2544-最短路(Dijkstra + Dijkstra优先队列 + Bellman-ford + SPFA +Floyd) 纯模板题

最短路


Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?


Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
 
Output

对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
 
Sample Input
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
 
Sample Output

3
2
 

题目链接:最短路


代码:


//Dijkstra
#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       

using namespace std;
const int MAX = 1 << 30;
int n,m,vis[110],dist[110];

struct node     //存储边的终点,以及权值
{
    int v,w;
    node(int vv,int ww) : v(vv),w(ww) {}
    node() {}
};

vector
       
       
         G[110]; void make_G() { int st,ed,c; for(int i = 1;i <= n;i++) { //初始化 G[i].clear(); vis[i] = 0; dist[i] = MAX; } for(int i = 0;i < m;i++) { scanf("%d%d%d",&st,&ed,&c); G[st].push_back(node (ed,c)); G[ed].push_back(node (st,c)); } } void dijkstra() { dist[1] = 0; for(int i = 0;i < n;i++) { //从未选点集中选点,并加入已选点集 int p,mn = MAX; for(int j = 1;j <= n;j++) { //未选点 中 距离 已选点 最近的点 if(!vis[j] && dist[j] <= mn) { p = j,mn = dist[j]; } } vis[p] = 1; //标记选择 for(int j = 0;j < G[p].size();j++) { //更新选择后的dist数组,也就是源点到其他点的最短距离 if(dist[G[p][j].v ] > dist[p] + G[p][j].w){ dist[G[p][j].v ] = dist[p] + G[p][j].w; } } } printf("%d\n",dist[n]); } int main() { while(~scanf("%d%d",&n,&m) && n && m) { make_G(); dijkstra(); } return 0; }#include 
        
          #include 
         
           #include 
          
            #include 
           
             using namespace std; int n,m,vis[110]; struct node { int v,w; node(int vv,int ww) : v(vv),w(ww) {} node() {} bool operator < (const node &a) const //运算符重载,保证权值小的边优先级高 { return w > a.w; } }; vector 
            
              G[110]; void make_G() { int st,ed,c; for(int i = 1;i <= n;i++) { G[i].clear(); vis[i] = 0; } for(int i = 0;i < m;i++) { scanf("%d%d%d",&st,&ed,&c); G[st].push_back(node (ed,c)); G[ed].push_back(node (st,c)); } } void dijkstra() { priority_queue 
             
               qe; qe.push(node (1,0)); node p; while(!qe.empty()) { p = qe.top(); qe.pop(); if(vis[p.v]) continue; //之前处理过(队列先处理最优的) vis[p.v] = 1; if(p.v == n) break; for(int i = 0;i < G[p.v].size();i++) { node q = G[p.v][i]; if(!vis[q.v]) { //从已选点开始可更新的边都入队,当然也可以改成判断队列是否已经有这条边 q.w = p.w + q.w; qe.push(node (q.v,q.w)); } } } printf("%d\n",p.w); } int main() { while(~scanf("%d%d",&n,&m) && n && m) { make_G(); dijkstra(); } return 0; }//bellman-ford #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   using namespace std; const int MAX = 1<<30; int n,m,vis[110],dist[110]; struct node { int u,v,w; node(int uu,int vv,int ww) : u(uu),v(vv),w(ww) {} node() {} }; vector 
                  
                    G; void make_G() { int st,ed,c; G.clear(); for(int i = 1;i <= n;i++) { vis[i] = 0; dist[i] = MAX; } for(int i = 0;i < m;i++) { scanf("%d%d%d",&st,&ed,&c); G.push_back(node (st,ed,c)); G.push_back(node (ed,st,c)); } } void bellman_ford() { dist[1] = 0; for(int j = 1;j < n;j++) { 
                    //n-1次松弛 for(int i = 0;i < G.size();i++) { 
                    //对每条边进行处理 int u,v; u = G[i].u,v = G[i].v; if(dist[v] > dist[u] + G[i].w) { dist[v] = dist[u] + G[i].w; } } for(int i = 0;i < G.size();i++) { 
                    //此题可以省略 int u,v; u = G[i].u,v = G[i].v; if(dist[v] > dist[u] + G[i].w) { printf("有环!\n"); } } } } int main() { while(~scanf("%d%d",&n,&m) && n && m) { make_G(); bellman_ford(); printf("%d\n",dist[n]); } return 0; }#include 
                   
                     #include 
                    
                      #include 
                     
                       #include 
                      
                        using namespace std; const int MAX = 1e7; int n,m,dist[110]; struct node { int v,w; node(int vv,int ww) : v(vv),w(ww) {} node() {} bool operator < (const node &a) const { return w > a.w; } }; vector 
                       
                         G[110]; void make_G() { int st,ed,c; for(int i = 1;i <= n;i++) { dist[i] = MAX; G[i].clear(); } for(int i = 0;i < m;i++) { scanf("%d%d%d",&st,&ed,&c); G[st].push_back(node (ed,c)); G[ed].push_back(node (st,c)); } } void spfa() { priority_queue 
                        
                          qe; int updataTimes[110]; memset(updataTimes,0,sizeof(updataTimes)); node p = node (1,0); qe.push(p); dist[p.v] = 0; while(!qe.empty()) { p = qe.top(); qe.pop(); for(int i = 0;i < G[p.v].size();i++) { node q = G[p.v][i]; if(dist[q.v] > dist[p.v] + q.w) { dist[q.v] = dist[p.v] + q.w; qe.push(node (q.v,dist[q.v])); if(++ updataTimes[q.v] >= n) { //更新次数超过n次,有环 printf("有环\n"); } } } } printf("%d\n",dist[n]); } int main() { while(~scanf("%d%d",&n,&m) && n && m) { make_G(); spfa(); } return 0; }#include 
                         
                           #include 
                          
                            #include 
                           
                             #include 
                            
                              using namespace std; const int MAX = 1 << 30; int n,m,path[110][110]; void make_G() { int st,ed,c; for(int i = 1;i <= n;i++) { for(int j = 1;j <= n;j++) { path[i][j] = MAX; } } for(int i = 0;i < m;i++) { scanf("%d%d%d",&st,&ed,&c); path[st][ed] = path[ed][st] = c; } } void floyd() { for(int k = 1;k <= n;k++) { 
                              //注意枚举点的循环的位置 for(int i = 1;i <= n;i ++) { for(int j = 1;j <= n;j++) { if(path[i][k] == MAX || path[k][j] == MAX) continue; if(path[i][j] > path[i][k] + path[k][j]) { path[i][j] = path[i][k] + path[k][j]; } } } } } int main() { while(~scanf("%d%d",&n,&m) && n && m) { make_G(); floyd(); printf("%d\n",path[1][n]); } return 0; } 
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   


                                                                                                                                                                                    



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值